#!/usr/bin/nodejs
var mosca = require('mosca');
const mysql = require('../core/mysql');
const common = require("../core/common");
const crypto = require('crypto');
var publishHandle = require('./publishHandle')

var ascoltatore = {
// using ascoltatore
 type: 'mongo',
 url: 'mongodb://localhost:27017/mqtt',
 pubsubCollection: 'ascoltatori',
 mongo: {}
};

var settings = {
    port: 1883,
 backend: ascoltatore
};

var server = new mosca.Server(settings);

server.on('clientConnected', function(client) {
    console.log('client connected', client.id);

});

server.on('authenticate',function(client,username,password,callback){
    console.log('username',username);
})
// fired when a message is received
server.on('published', function(packet, client) {
    let topic = packet.topic;
    topic = topic.replace(/^\s+|\s+$/g,"");//去除空格
    let topics = topic.split("/");
    if(topics[0]=='publish'){
        console.log('Published', packet.payload.toString());
        publishHandle.publishDistribute(topics[1],packet.payload.toString())
    }

    //提取topic，只提取正常publish得数据
});

server.on('subscribed', async function(packet, client) {
    console.log('subscribed', packet);

    let payload =  await getParkStatus(client.id);

    sendClients(packet,JSON.stringify(payload))
});
server.on('ready', setup);

// fired when the mqtt server is ready
function setup() {
    console.log('Mosca server is up and running');
    // server.authenticate = authenticate;
}
// 验证用户信息
var authenticate = async function(client, username, password, callback) {
    console.log("client---->username",username)
    if(username==null)
        return;
    //json字符串转对象
    let object = JSON.parse(username?username:"");

    let imei = object.imei;
    //首先判断IMEI是否存在，其次从terminal表中取出salt进行加密验证是否sign相同，不同不允许建立连接，相同才可以
    let sql = `select * from t_terminal where imei_code ='${imei}'`;
    console.log("sql",sql)
    let result = await mysql.querySync(sql);
    if(result.length!=1){//说明IMEI不存在或有多个
        await common.saveInvalidLog(imei,"imei不存在或存在多个，个数"+result.length);
        return;
    }else{//对sign进行验证
        let salt = result[0].salt;
        let timestamp = object.timestamp;
        let sign = object.sign;
        var b = new Buffer(imei.toString()+timestamp.toString());
        var s = b.toString('base64');
        let str = myMD5(s+salt)
        str = myMD5(str);
        if(str!=sign){//说明终端非法，记录在案，并拒绝连接
            await common.saveInvalidLog(imei,"imei终端非法，签名未通过"+result.length);
            return;
        }else{
            callback(null, true);
        }
    }
}

/**
 *  md5加密
 **/
function myMD5(param){ //暴露出md5s方法
    let md5 = crypto.createHash('md5');
    md5.update(param);
    let str=md5.digest('hex');
    let s=str.toUpperCase();  //32位大写
    console.log(s);
    return s;
}

/**
 * 查询imei对应得车位状态给客户端
 */
async function  getParkStatus(imei) {
    //根据imei查询车位状态
    let sql = `select * from t_park  a
                left join t_terminal b on a.terminal_id = b.terminal_id 
                where b.imei_code = ${imei}
    
    `;
    let payload = {"type":"parkStatus2"}
    let result = await mysql.querySync(sql);
    if(result.length>0){//说明设备还未有车位状态变化，此时，将左右车位状态都为无车状态
            //将两个车位状态更改为数据库状态
            for(let i=0;i<result.length;i++){
                let park_status = result[i].park_status;
                let parknum = result[i].park_num;
                payload[parknum] = park_status;
            }
    }
    return payload;
}
/**
 * mosca发送给客户端得数据
 **/
function sendClients(topic,payload) {
    console.log("payload",payload)
    let message = {
        topic: topic,
        payload: payload, // or a Buffer
        qos: 1, // 0, 1, or 2
        retain: false // or true
    };

    server.publish(message, function() {
        console.log('done!');
    });
}